module EXE_reg(
  input clk,
  input rst,
  input flush,
  input enable,
  input ready,

  input difftest_raise_hard_intr_i,
  input [63:0] pc_i,
  input [31:0] inst_i,
  input load_valid_i,
  input [63:0] load_addr_i,
  input [3:0] load_bytes_i,
  input load_sign_i,
  input store_valid_i,
  input [63:0] store_addr_i,
  input [63:0] store_data_i,
  input [3:0] store_bytes_i,
  input [4:0] dest_i,
  input [63:0] dest_data_i,
  input dest_valid_i,
  input [63:0] mul_res_i,
  input [63:0] div_res_i,
  input [1:0] other_op_i,
  
  output difftest_raise_hard_intr_o,
  output [63:0] pc_o,
  output [31:0] inst_o,
  output load_valid_o,
  output [63:0] load_addr_o,
  output [3:0] load_bytes_o,
  output load_sign_o,
  output store_valid_o,
  output [63:0] store_addr_o,
  output [63:0] store_data_o,
  output [3:0] store_bytes_o,
  output [4:0] dest_o,
  output [63:0] dest_data_o,
  output dest_valid_o,
  output [1:0] other_op_o,


  output hazards_dst_valid_o,
  output [63:0] hazards_data_o,
  output [4:0] hazards_dest_o,
  output hazards_data_valid_o
);
  localparam VALID_WIDTH = 3;
  wire [VALID_WIDTH-1:0] valid_i = {load_valid_i,store_valid_i,dest_valid_i};
  wire [VALID_WIDTH-1:0] valid_o;
  Reg #(.WIDTH(VALID_WIDTH), .RESET_VAL({VALID_WIDTH{1'b0}})) reg_valid (.clk(clk), .rst(rst|flush), .din(valid_i), .dout(valid_o), .wen(enable));
  assign {load_valid_o,store_valid_o,dest_valid_o} = valid_o&{VALID_WIDTH{ready}};

  wire [1:0] other_op_r;
  Reg #(.WIDTH(2), .RESET_VAL(2'b0)) reg_other_op (.clk(clk), .rst(rst|flush), .din(other_op_i), .dout(other_op_r), .wen(enable));
  assign other_op_o = other_op_r&{2{ready}};

  wire [63:0] dest_data_o_r;
  assign dest_data_o = dest_data_o_r|mul_res_i|div_res_i;
  localparam DATA_WIDTH = 64+4+1+64+64+4+5+64;
  wire [DATA_WIDTH-1:0] data_i = {load_addr_i,load_bytes_i,load_sign_i,store_addr_i,store_data_i,store_bytes_i,dest_i,dest_data_i};
  wire [DATA_WIDTH-1:0] data_o;
  Reg #(.WIDTH(DATA_WIDTH), .RESET_VAL({DATA_WIDTH{1'b0}})) reg_data (.clk(clk), .rst(rst|flush), .din(data_i), .dout(data_o), .wen(enable));
  assign {load_addr_o,load_bytes_o,load_sign_o,store_addr_o,store_data_o,store_bytes_o,dest_o,dest_data_o_r} = data_o;

  Reg #(.WIDTH(97), .RESET_VAL(97'b0)) reg_pc_inst (.clk(clk), .rst(rst|flush), .din({inst_i,pc_i,difftest_raise_hard_intr_i}),   .dout({inst_o,pc_o,difftest_raise_hard_intr_o}), .wen(enable));

  assign hazards_dst_valid_o = valid_o[0]|valid_o[2];
  assign hazards_data_valid_o = valid_o[0];
  assign hazards_data_o = dest_data_o;
  assign hazards_dest_o = dest_o;
endmodule
